<?php
/**
 * Created by PhpStorm.
 * User: DaibiDaddy
 * Date: 2016/5/24
 * Time: 17:14
 */

namespace App\Base;

use App\BaseExt\Pagination;

use Doctrine\ORM\EntityManager;
use Symfony\Bridge\Monolog\Logger;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Serializer\Serializer;

require_once(__DIR__ . "/../Consts/Date.php");
require_once(__DIR__ . "/../Consts/Exception.php");
require_once(__DIR__ . "/../Consts/Citys.php");
require_once(__DIR__ . "/../Consts/App.php");
require_once(__DIR__ . "/../Consts/CommonConst.php");

class BaseController extends AbstractController
{


    public $YYMMDDHHIISS = "Y-m-d H:i:s";
    public $YMDHIS = "YmdHis";
    public $HHIISS = "H:i:s";
    public $YYMMDD = "Y-m-d";

    /**@var $serializer Serializer */
    public $serializer;
    public $documentManager;
    public $baseCache;

    /**@var $logger Logger */
    public $logger;
    public $formCreator;

    public $groups = [];//可以设置数据展示的分组
    public $meta = [];//可以设置分页数据

    public function __construct()
    {
        $this->baseCache = new BaseCache();
    }


    public function jumpToRoute($route)
    {
        header("location:" . $this->generateUrl($route));
        exit;
    }

    public function jumpToURL($url)
    {
        header("location:$url");
        exit;
    }

    /**
     * json 格式输出结果
     * @param $status
     * @param $info
     * @param array $data
     * @return Response
     */
    public function json_out($status, $info, $data = array())
    {
        $request = Request::createFromGlobals();
        $access_token = $this->getAccessToken();
        $data = array(
            "s" => $status ? $status : 0,
            "i" => $info ? $info : "",
            "d" => $data ? $data : ""
        );

        $context =[];
        if ($this->groups) {
            $context["groups"] = $this->groups;
        }
        return $this->json(
            $data,
            200,
            ["content-type"=>"application/json","access-token"=>$access_token],
            $context
        );
//        return new Response(json_encode($data), 200
//            , array(
//                "content-type" => "application/json",
//                "access-token" => $access_token,
//            ),$context);
    }

    /**
     * js弹窗提示结果后跳转
     * @param $msg
     * @param $path
     * @return Response
     */
    public function js_out($msg, $path = "javascript:history.go(-1);")
    {

        if (!$path || $path == "javascript:history.go(-1);") {
            $path = false;
        }
        $data = array(
            "s" => 1,
            "i" => $msg,
            "d" => $path,
        );
        return new Response(json_encode($data), 200, array("content-type" => "application/json"));
//        $data = array(
//            "url"   => $path,
//            "msg"   => $msg,
//        );
//        return $this->render("LazyCommon/message.html.twig",$data);

    }


    /**
     * 获取必填参数
     * @param $paramName
     * @return bool|mixed
     */
    public function getParamRequired($paramName)
    {
        $request = Request::createFromGlobals();
        if ($request->request->has("$paramName")) {
            return $request->get("$paramName");
        }
        if ($request->query->has("$paramName")) {
            return $request->get("$paramName");
        }
        return false;
    }

    /**
     * @param $base_url
     * @param $total_rows
     * @param int $per_page
     * @return array
     */
    public function creatPage($base_url, $total_rows, $per_page = 10)
    {
        $config['first_url'] = $base_url;
        $config['base_url'] = $base_url;
        $config['total_rows'] = $total_rows;
        $config['per_page'] = $per_page;
//        $config['reuse_query_string'] = TRUE;
//        $config["query_string_segment"] = "page";

        //分页基础配置
        $config['num_links'] = 7;
        $config['first_link'] = '首页';
        $config['prev_link'] = '«上一页';
        $config['cur_tag_open'] = '<li class="page-item active"><a class="page-link">';
        $config['cur_tag_close'] = '</a></li>';
        $config['next_link'] = '下一页»';
        $config['last_link'] = '末页';

        $pageBuilder = new Pagination($config);
        $page = $pageBuilder->create_links();
        return array(
            "total" => $total_rows,
            "perPage" => $per_page,
            "page" => $page
        );
    }

    /**
     * @return FormCreator
     */
    public function getFormCreator()
    {
//        return $this->get("App\Base\FormCreator");
//        return new FormCreator();
        return $this->formCreator;
    }

    public function createMyForm($FBNameSpace, $entity, $actionUrl = "", $method = "POST", $confName = "formConfig")
    {
        $config = array(
            "entity" => $entity,
            "actionUrl" => $actionUrl,

        );
        $options = array(
            "attr" => array(
                "action" => $actionUrl,
                "method" => $method,
            ),
        );

        $form = $this->createFormBuilder($config["entity"], $options)->getForm();
//        $m = $this->getDoctrine()->getManager();
        $m = $this->getDoctrine();
        $formRows = new $FBNameSpace($m);
        foreach ($formRows->$confName() as $key => $param) {
            $form->add(
                $key,
                $this->type2RealType($param["showType"]),
                $this->basicParam($param["showType"], $param["label"], $param["dataType"], $param["option"], isset($param["class"]) ? $param["class"] : "")
            );
        }
        return $form;
    }

    /*项目通用化增删改查*/
    public $entitySetting;

    public function setSetting($entitySetting)
    {
        $this->entitySetting = $entitySetting;
    }

    public function autoFillEntity($entity, $keys)
    {
        $request = Request::createFromGlobals();
        $form = $this->createFormBuilder($entity)->getForm();
        foreach ($keys as $key) {
            $form->add($key);
        }
        $form->handleRequest($request);
        $entity = $form->getData();
//        var_dump($entity);
        $this->myEm()->persist($entity);
        $this->myEm()->flush();
        return $entity;
    }


    public function buildeCatTree($data, $table = "")
    {
        if ($table) {
            $table = $table . "_";
        }
        $newData = array();
        foreach ($data as $d) {//根据parent取出子项
            $newData[$d[$table . "id"]] = $d;
        }
        $groupByParent = array();
        foreach ($newData as $d) {//根据parent取出子项
            $groupByParent[$d[$table . "parent"]][$d[$table . "orders"] * 1000000 + $d[$table . "id"]] = $d;
        }

        $curParent = 0;
        $isEnd = 0;
        $sortedArray = array();
        $i = 0;
        if (isset($groupByParent[$curParent])) {
            do {
                ksort($groupByParent[$curParent]);
                if (isset($groupByParent[$curParent])) {//此ID下有分类
                    //设置这个父元素的相邻父元素
                    $first = reset($groupByParent[$curParent]);
                    //取出当前分组的第一个元素并删除
                    $sortedArray[] = $first;
                    array_shift($groupByParent[$curParent]);
                    if (isset($groupByParent[$first[$table . "id"]])) {//查找子元素
                        $curParent = $first[$table . "id"];
                    } else {//子元素没有的时候需要检测时候还有兄弟元素
                        while (empty($groupByParent[$curParent])) {
                            unset($groupByParent[$curParent]);
                            if ($curParent == 0) {
                                $isEnd = 1;
                                break;
                            }
                            $curParent = $newData[$curParent][$table . "parent"];
                        }
                    }
                    if ($isEnd) {
                        break;
                    }
                }
                $i++;
            } while (count($sortedArray) < count($newData) && $i < 100);
        } else {
            $sortedArray = $newData;
        }
        return $sortedArray;
    }


    public function comTools(Request $request)
    {
        if ($__EVENTTARGET = $this->getParamRequired("__EVENTTARGET")) {
            unset($_GET['__EVENTTARGET']);
        } else {
            return $this->js_out("参数丢失", $this->redirectToRoute($this->entityName . "Lists"));
        }
        if ($__EVENTARGUMENT = $this->getParamRequired("__EVENTARGUMENT")) {
            unset($_GET['__EVENTARGUMENT']);
        }
        $em = $this->myEm();
        //如果是删除操作执行删除操作
        if ($__EVENTTARGET == "multiDelete") {
            if ($ids = $this->getParamRequired("ids")) {
                unset($_GET['ids']);
            } else {
                return $this->js_out("参数丢失", $this->redirectToRoute($this->entityName . "Lists"));
            }
            if (is_array($ids) && !empty($ids)) {
                foreach ($ids as $id) {
                    if (property_exists($this, "noDelete")) {

                        if (in_array(0, $this->noDelete)) {
                            continue;
                        }
                        if (in_array($id, $this->noDelete)) {
                            continue;
                        }
                    }
                    $entity = $em->find("App:" . $this->entityName, $id);
                    $em->remove($entity);
                }
                $em->flush();
            }
        }
        //如果是修改操作执行修改操作
        if ($__EVENTTARGET == "setAttr") {
            parse_str($__EVENTARGUMENT, $data);
            if (is_array($data) && isset($data["id"])) {
                $entity = $em->find("App:" . $this->entityName, $data["id"]);
                unset($data["id"]);
                foreach ($data as $key => $val) {
                    if (!in_array($key, $this->editKeys)) {
                        continue;
                    }
                    $func = "set$key";
                    $func = str_replace("_", "", $func);
                    $entity->$func($val);
                }
                $em->persist($entity);
                $em->flush();
            }
        }
        //否则将参数传递至list
        $cond["cond"] = $request->get("cond");
        $queryStr = http_build_query($cond);
        if ($txtKeywords = $request->get("txtKeywords")) {
            $queryStr .= "&txtKeywords=" . $txtKeywords;
        }
        return $this->redirect($this->generateUrl($this->entityName . "Lists") . "?" . $queryStr);
    }


    /**
     * @param $entity
     * @param $depth
     * @return array
     */
    public function toArray($entity, $depth = 0)
    {
        return IRI::toArray($entity);
//        if (!$entity) return [];
//        $methods = (get_class_methods(get_class($entity)));
//        $arrData = array();
//        foreach ($methods as $method) {
//            if ($method == "__construct") {
//                continue;
//            }
//            if (substr($method, 0, 3) == "add") {
//                continue;
//            }
//            if (substr($method, 0, 6) == "remove") {
//                continue;
//            }
//            $attr = lcfirst(substr($method, 3));
//            $funcName = "get" . ucfirst($attr);
//            $val = $entity->$funcName();
//            $arrData[$attr] = $val;
//        }
//        $entity = $arrData;
//        return $arrData;
    }


    /**
     * @param $entity
     * @return array
     */
    public function normalize(&$entity)
    {

        if (!$entity) return [];
        $context = [];
        if ($this->groups) {
            $context["groups"] = $this->groups;
        }
        return json_decode($this->serializer->serialize($entity, "json", $context), true);
    }

    /**
     * @return Session
     */
    public function mySession()
    {
        return $this->get("session");
    }

    public function getAccessToken()
    {
        return (new BaseCache())->getUserAccessToken(Request::createFromGlobals());
    }

    /**
     * @return BaseCache
     */
    public function myCache()
    {

        $access_token = (new BaseCache())->getUserAccessToken(Request::createFromGlobals());
        $bc = new BaseCache();
        return $bc;
    }
    public function userCache()
    {
        $access_token = $this->baseCache->getUserAccessToken(Request::createFromGlobals());
        return $this->baseCache->getItem($access_token);
    }

    public function setUserCache($key,$val)
    {
        $uc = $this->userCache();
        if (!is_array($uc)) {
            $uc = [];
        }
        $uc[$key] = $val;
        $access_token = $this->baseCache->getUserAccessToken(Request::createFromGlobals());
        $this->baseCache->setItem($access_token,$uc);
    }

    public function getUserCache($key)
    {
        $uc = $this->userCache();
        if (!is_array($uc)) {
            return null;
        }
        return $uc[$key] ?? null;
    }


    /**
     * @return \Doctrine\Common\Persistence\ObjectManager|EntityManager
     */
    public function myEm()
    {
        return $this->getDoctrine()->getManager();
    }

    public function myRep($name)
    {
        return $this->getDoctrine()->getRepository($name);
    }


    public function setSessionData($array)
    {
        $session = $this->mySession();
        foreach ($array as $k => $v) {
            $session->set("$k", $v);
        }
    }

    public function getSessionData($key)
    {

        $session = $this->mySession();
        return $session->get($key);
    }

    public function getTokenData()
    {
        $BaseCache = new BaseCache();
        $access_token = $BaseCache->getUserAccessToken(Request::createFromGlobals());
        $userInfo = $BaseCache->getItem($access_token);
        return $userInfo;
    }

    /*********************验证码相关************************/
    //获取图片验证码
    /**
     * @param $headPics
     * @return array
     */
    public function createImgFromHead($headPics)
    {
        $code = "";
        $url = array();
        foreach ($headPics as $key => $headPic) {
            $rnd = rand(0, 3);
            $source = imagecreatefrompng("." . $headPic);
            $rotate = imagerotate($source, 90 * $rnd, 0);
            //旋转后的图片保存
            //创建临时目录
            if (!is_dir("./tmp/headCaptcha/" . date("Ymd"))) {
                mkdir("./tmp/headCaptcha/" . date("Ymd"));
            }
            $savePath = "/tmp/headCaptcha/" . date("Ymd") . "/" . uniqid() . rand(111111, 999999) . ".png";
            imagepng($rotate, "." . $savePath);
            $code .= $rnd;
            $url[] = $savePath;
        }
        return array(
            "code" => $code,
            "urls" => $url
        );
    }

    public function checkHeadCaptchaCode($code)
    {

        $cap = $this->getSessionData("headCaptcha");
        return $cap == $code;
    }
//
//
//    public function fillEntityFromRequest(&$entity)
//    {
//        $orgData = $entity;
//        $params = $this->toArray($orgData);
//        foreach ($params as $key => $value) {
//            if ($key == "id") {
//                continue;
//            }
//            if (!$$key = $this->getParamRequired("$key")) {
//                if ($$key === false) {
//                    continue;
//                }
//            }
//            $func = "set" . ucfirst($key);
//            $entity->$func($$key);
//        }
//        return $entity;
//    }

    /**
     * @param array $old
     * @param array $new
     * @param string $prefix
     * @return mixed
     */
    public function concat($old, $new, $prefix = "")
    {
        foreach ($new as $key => $value) {
            $old[$prefix . ucfirst($key)] = $value;
        }
        return $old;
    }

    public function getAssetBaseUrl()
    {
        if (BaseConfig::__OSS_OPEN__ == 0) {
            return BaseConfig::__BASE_URL__;
        } else {
            return BaseConfig::__OSS_URL__;
        }
    }

    public function dealWithImgInHtml($content)
    {
        $pregRule = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.jpg|\.jpeg|\.png|\.gif|\.bmp]))[\'|\"].*?[\/]?>/";
        if (BaseConfig::__HTML_OSS_OPEN__ == 0) {
            $content = preg_replace($pregRule, '<img src="' . $this->getParameter("base_url") . '${1}" style="max-width:100%">', $content);
        } else {
            $content = preg_replace($pregRule, '<img src="' . $this->getParameter("oss_url")  . '${1}" style="max-width:100%">', $content);
        }
        return $content;
    }

    /**
     * @param $code
     * @param $time
     * @param $string
     * @return bool
     */
    public function checkVICode($code, $time, $string)
    {//string 生成：$phone + md5(md5($password))
        if (strtolower($code) == strtolower(md5($string . $time . BaseConfig::__VI__ . $time . $string))) {
            return true;
        } else {
            return false;
        }
    }

    public function dealWithPhoneNumber($phone)
    {
        $start = substr($phone, 0, 3);
        $end = substr($phone, -4);
        return $start . "****" . $end;
    }


    public function excelOut($title, $arrayData, $fileName, $indexArray = [])
    {
        require_once(__DIR__ . "/../../BaseExt/PHPExcel.php");
        $excel = new \PHPExcel();
        $excelHelper = new \ExcelAssistant();
        $titleLetter = $excelHelper->GetExcelTit(count($title));
//        var_dump($titleLetter);
        //设置标题
        $i = 0;
        foreach ($title as $key => $name) {
            if ($indexArray) {
                if (!in_array($i, $indexArray)) {
                    continue;
                }
            }
            $excel->getActiveSheet()->setCellValue($titleLetter[$key] . "1", $name);
        }

        //设置内容
        foreach ($arrayData as $key => $row) {
            $i = 0;
            foreach ($row as $k => $v) {
                if (!is_string($v)) {
                    $v = json_encode($v);
                }
                $excel->getActiveSheet()->setCellValue($titleLetter[$i] . ($key + 2), $v);
                $i++;
            }
        }

//        直接输出到浏览器
        $objWriter = new \PHPExcel_Writer_Excel5($excel);
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
        header("Content-Type:application/force-download");
        header("Content-Type:application/vnd.ms-execl");
        header("Content-Type:application/octet-stream");
        header("Content-Type:application/download");;
        header('Content-Disposition:attachment;filename="' . $fileName . '.xls"');
        header("Content-Transfer-Encoding:binary");

        $request = Request::createFromGlobals();
        $url = $request->headers->get("origin");
        header("Access-Control-Allow-Origin:$url");

        $objWriter->save('php://output');
    }


    public function excelRead($path)
    {
        require_once(__DIR__ . "/../../BaseExt/PHPExcel.php");
//        $excel = new \PHPExcel();
        $path = "." . $path;

        /**默认用excel2007读取excel，若格式不对，则用之前的版本进行读取*/
        $PHPReader = new \PHPExcel_Reader_Excel2007();
        if (!$PHPReader->canRead($path)) {
            $PHPReader = new \PHPExcel_Reader_Excel5();
            if (!$PHPReader->canRead($path)) {
                echo 'no Excel';
                return;
            }
        }
        $re = array();
        $PHPExcel = $PHPReader->load($path);
        /**读取excel文件中的第一个工作表*/
        $currentSheet = $PHPExcel->getSheet(0);
        /**取得最大的列号*/
        $allColumn = $currentSheet->getHighestColumn();
        /**取得一共有多少行*/
        $allRow = $currentSheet->getHighestRow();
        /**从第二行开始输出，因为excel表中第一行为列名*/
        for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
            /**从第A列开始输出*/
            for ($currentColumn = 'A'; $currentColumn <= $allColumn; $currentColumn++) {
                $val = $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue();
                /**ord()将字符转为十进制数*/
                $re[$currentRow - 2][] = $val;
            }
        }
        return $re;
    }



    public function getRequestData()
    {
        $request = Request::createFromGlobals();
        if (!$data = $request->request->all()) {
            if (!$data = $request->query->all()) {
                $data = $request->getContent();
                if (is_string($data)) {
                    $data = json_decode($data, true);
                }
            }
        }

        if (!$data) {
            $data = [];
        }else{
            foreach ($data as $key=>&$val) {
                if (is_string($val)) {
                    try {

                        $tmp = json_decode($val,true);
                        if ($tmp) {
                            $val = $tmp;
                        }
                    } catch (\Exception $exception) {
                        //什么也不做
                    }
                }
            }
        }
        return $data;
    }

    public function setGroups($group)
    {
        if ($group) {
            $this->groups = func_get_args();
        } else {
            $this->groups = [];
        }

        return $this;
    }
    public function clearGroups()
    {
        $this->groups = [];
        return $this;
    }

    public function setMeta($cur, $total, $limit)
    {
        $this->meta = [
            "current_page" => $cur,
            "total" => $total,
            "per_page" => $limit,
        ];
    }

    public function createEntity($data, $class)
    {
        $context = [];
        if ($this->groups) {
            $context["groups"] = $this->groups;
        }
        foreach ($data as $key => &$val) {
            $val = IRI::create($class, $key, $val);
        }
        return $this->serializer->denormalize($data, $class, "json", $context);
    }

    public function updateEntity($data, $class, $entity)
    {
        $context = [];

        $context["object_to_populate"] = $entity;
        if ($this->groups) {
            $context["groups"] = $this->groups;
        }
        foreach ($data as $key => &$val) {
            $val = IRI::create($class, $key, $val);
        }
        return $this->serializer->denormalize($data, $class, "json", $context);
    }

}
